package logger

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"time"
)

// PerformanceMetrics 性能指标结构
type PerformanceMetrics struct {
	Timestamp time.Time `json:"timestamp"`
	NodeID    int       `json:"node_id"`
	TPS       float64   `json:"tps"`
	Latency   int64     `json:"latency_ms"`
	Epoch     int       `json:"epoch"`
	BatchSize int       `json:"batch_size"`
	TxSize    int       `json:"tx_size"`
	MemoryMB  float64   `json:"memory_mb"`
	CPUUsage  float64    `json:"cpu_usage"`
}

// PerformanceLogger 性能日志记录器
type PerformanceLogger struct {
	nodeID     int
	logDir     string
	logFile    *os.File
	mu         sync.RWMutex
	interval   time.Duration
	stopChan   chan struct{}
	metrics    []PerformanceMetrics
}

// NewPerformanceLogger 创建新的性能日志记录器
func NewPerformanceLogger(nodeID int, logDir string, interval time.Duration) (*PerformanceLogger, error) {
	// 确保日志目录存在
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("failed to create log directory: %v", err)
	}

	// 创建日志文件
	logFile := filepath.Join(logDir, fmt.Sprintf("node_%d_performance.log", nodeID))
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return nil, fmt.Errorf("failed to open log file: %v", err)
	}

	pl := &PerformanceLogger{
		nodeID:   nodeID,
		logDir:   logDir,
		logFile:  file,
		interval: interval,
		stopChan: make(chan struct{}),
		metrics:  make([]PerformanceMetrics, 0),
	}

	// 启动定期记录
	go pl.periodicLog()

	return pl, nil
}

// RecordMetrics 记录性能指标
func (pl *PerformanceLogger) RecordMetrics(tps float64, latency int64, epoch int, batchSize int, txSize int) {
	pl.mu.Lock()
	defer pl.mu.Unlock()

	metric := PerformanceMetrics{
		Timestamp: time.Now(),
		NodeID:    pl.nodeID,
		TPS:       tps,
		Latency:   latency,
		Epoch:     epoch,
		BatchSize: batchSize,
		TxSize:    txSize,
		MemoryMB:  pl.getMemoryUsage(),
		CPUUsage:  pl.getCPUUsage(),
	}

	pl.metrics = append(pl.metrics, metric)
}

// periodicLog 定期记录日志
func (pl *PerformanceLogger) periodicLog() {
	ticker := time.NewTicker(pl.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			pl.logCurrentMetrics()
		case <-pl.stopChan:
			return
		}
	}
}

// logCurrentMetrics 记录当前指标
func (pl *PerformanceLogger) logCurrentMetrics() {
	pl.mu.RLock()
	defer pl.mu.RUnlock()

	if len(pl.metrics) == 0 {
		return
	}

	// 获取最新的指标
	latest := pl.metrics[len(pl.metrics)-1]

	// 写入日志文件
	logEntry := fmt.Sprintf("[%s] Node-%d: TPS=%.2f, Latency=%dms, Epoch=%d, BatchSize=%d, TxSize=%d, Memory=%.2fMB, CPU=%.2f%%\n",
		latest.Timestamp.Format("2006-01-02 15:04:05"),
		latest.NodeID,
		latest.TPS,
		latest.Latency,
		latest.Epoch,
		latest.BatchSize,
		latest.TxSize,
		latest.MemoryMB,
		latest.CPUUsage)

	pl.logFile.WriteString(logEntry)
	pl.logFile.Sync()

	// 同时输出到控制台
	fmt.Print(logEntry)
}

// getMemoryUsage 获取内存使用量 (MB)
func (pl *PerformanceLogger) getMemoryUsage() float64 {
	// 简化实现，实际应该读取 /proc/self/status
	return 0.0
}

// getCPUUsage 获取CPU使用率 (%)
func (pl *PerformanceLogger) getCPUUsage() float64 {
	// 简化实现，实际应该读取 /proc/stat
	return 0.0
}

// ExportMetrics 导出指标到JSON文件
func (pl *PerformanceLogger) ExportMetrics() error {
	pl.mu.RLock()
	defer pl.mu.RUnlock()

	jsonFile := filepath.Join(pl.logDir, fmt.Sprintf("node_%d_metrics.json", pl.nodeID))
	file, err := os.Create(jsonFile)
	if err != nil {
		return fmt.Errorf("failed to create JSON file: %v", err)
	}
	defer file.Close()

	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "  ")
	return encoder.Encode(pl.metrics)
}

// Stop 停止日志记录器
func (pl *PerformanceLogger) Stop() {
	close(pl.stopChan)
	pl.logFile.Close()
}

// GetMetrics 获取所有指标
func (pl *PerformanceLogger) GetMetrics() []PerformanceMetrics {
	pl.mu.RLock()
	defer pl.mu.RUnlock()
	return pl.metrics
}
